#include<iostream>
#include<string>
#include<vector>
#include<memory>
#include<algorithm>
#include"StrBlob.h"
using namespace std;
void practice_13_30();
void practice_13_31();
class HasPtr{
friend void swap(HasPtr&,HasPtr&);
friend ostream& print(ostream&,HasPtr&);
public:
	//the constructor allocated new string and its counter,and set the counter to 1;
	HasPtr(const string &s=string()):ps(new string(s)),i(0),use(new size_t(1)){}
	HasPtr(const string &s,const int &v):ps(new string(s)),i(v),use(new size_t(1)){}
	//the copy constructor copies all the members;
	HasPtr(const HasPtr &hp):ps(hp.ps),i(hp.i),use(hp.use){++*use;}
	HasPtr& operator=(const HasPtr &hp);
	bool operator<(const HasPtr &hp);
	~HasPtr();
private:
	string *ps;
	int i;
	size_t *use;//to record how many objects shared the pointer ps;
};
class TreeNode{
public:
	TreeNode(const string &v=string("")):value(v),count(new int(1)),left(nullptr),right(nullptr){}
	TreeNode(const TreeNode &t):value(t.value),count(t.count),left(t.left),right(t.right){++*count;}
	TreeNode& operator=(const TreeNode &t);
	~TreeNode();
private:
	string value;
	int *count;
	TreeNode *left;
	TreeNode *right;

};
class BinStrTree{
public:
	BinStrTree():root(new TreeNode()){}
	BinStrTree(const TreeNode *t_root):root(new TreeNode(*t_root)){}
	BinStrTree(const BinStrTree &bst):root(new TreeNode(*bst.root)){}
	BinStrTree& operator=(const BinStrTree &bst);
	~BinStrTree();
private:
	TreeNode *root;
};
HasPtr& HasPtr::operator=(const HasPtr &hp)
{
	++*hp.use;
	if(--*use==0)
	{
		delete ps;
		delete use;
	}
	this->ps=hp.ps;
	this->i=hp.i;
	this->use=hp.use;
	return *this;
}
bool HasPtr::operator<(const HasPtr &hp)
{
	if(this->i==hp.i)
	{
		return *this->ps<*hp.ps;
	}
	else
	 	return this->i<hp.i;
}
HasPtr::~HasPtr()
{
	if(--*use==0)
	{
		delete ps;
		delete use;
	}
}
TreeNode::~TreeNode()
{
	if(--*count==0)
	{
		if(left)
		{
			delete left;
			left=nullptr;
		}
		if(right)
		{
			delete right;
			right=nullptr;
		}
		delete count;
		count=nullptr;
	}
}
TreeNode& TreeNode::operator=(const TreeNode& t)
{
	++*t.count;
	if(--*count==0)
	{
		if(left)
		{
			delete left;
			left=nullptr;
		}
		if(right)
		{
			delete right;
			right=nullptr;
		}
		delete count;
		count=nullptr;
	}
	this->count=t.count;
	this->value=t.value;
	this->left=t.left;
	this->right=t.right;
	return *this;

}
BinStrTree::~BinStrTree()
{
	delete root;
}
BinStrTree& BinStrTree::operator=(const BinStrTree &bst)
{
	TreeNode *new_root=new TreeNode(*bst.root);
	delete root;
	root=new_root;
	return *this;
}
inline void swap(HasPtr &lhs,HasPtr &rhs)
{
	using std::swap;
	swap(lhs.ps,rhs.ps);
	swap(lhs.i,rhs.i);
}
ostream& print(ostream& os,HasPtr& hp)
{
	os<<*hp.ps<<" "<<hp.i;
}
void practice_13_30()
{
	HasPtr hp1("zyl",6);
	print(cout,hp1)<<endl;
	HasPtr hp2("zyl2",7); 
	print(cout,hp2)<<endl;
	swap(hp1,hp2);
	print(cout,hp1)<<endl;
	print(cout,hp2)<<endl;
}
void practice_13_31()
{
	HasPtr hp1("hp1",6);
	HasPtr hp2("hp2",6);
	HasPtr hp3("hp3",7);
	HasPtr hp4("hp4",8);
	vector<HasPtr> v{hp2,hp3,hp1,hp4};
	sort(v.begin(),v.end());
	for(auto h:v)
		print(cout,h)<<endl;

}
int main()
{	
	practice_13_31();
	return 0;
}